#include "propertydlg.hpp"
#include "ui_propertydlg.h"
#include "dbusargvitem.hpp"
#include "dbusvaluedelegate.hpp"
#include <qmessagebox.h>
#include "localmethod.hpp"



PropertyDlg::PropertyDlg(const BusSignatureEx data, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::PropertyDlg)
{
     ui->setupUi(this);
    ui->laType->setText ("");
    ui->laType->setHidden (true);
    ui->laBus->setText (QString("Addr:%1").arg (data.mBus));
    ui->laService->setText (QString("Service:%1").arg (data.mService));
    ui->laPath->setText (QString("Path:%1").arg (data.mPath));
    ui->laInterface->setText (QString("Interface:%1").arg (data.mInterface));
    ui->laName->setText (QString("method:%1").arg(data.mName));
    ui->leTimeout->setValidator (new QIntValidator(this));
    ui->leTimeout->setPlaceholderText(tr("milliseconds"));
    QString str;
    foreach (auto var, data.argTypes) {
        str.append (var);
    }
    ui->laArgs->setText (QString("args:%1").arg(str));
    m_category = data.type;
    if(data.type == MethodItem)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (false);
        m_model = new DBusArgvModel(data.argNames,data.argTypes,this);
        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);

        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
    }else if(data.type == PropertyItemReadwrite)
    {
        ui->gbProperty->setHidden (false);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (true);
        ui->cbPropertyGet->setEnabled (true);
        ui->cbPropertyGet->setCheckState (Qt::Checked);
        ui->leTimeout->setValidator (new QIntValidator(this));

        m_model = new DBusArgvModel(data.argNames,data.argTypes,this);

        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);

        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);

    }else if(data.type == PropertyItemRead)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (true);
        ui->cbPropertyGet->setEnabled (false);
        ui->cbPropertyGet->setCheckState (Qt::Checked);
    }else if(data.type == PropertyItemWrite)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (false);
        ui->cbPropertyGet->setEnabled (false);
        ui->cbPropertyGet->setCheckState (Qt::Unchecked);
        m_model = new DBusArgvModel(data.argNames,data.argTypes,this);
        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);
        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
    }else if(data.type == SignalItem)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (false);
        ui->treeView->setHidden (true);
        ui->btOk->setEnabled (true);
    }else if(data.type == LocalMethod)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (false);
        m_model = new DBusArgvModel(data.argNames,data.argTypes,this);
        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);

        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
    }
//    ui->treeView->adjustSize ();
    adjustSize();
}

PropertyDlg::PropertyDlg(const BusSignatureEx data, const QList<DVariant> values, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::PropertyDlg),
    m_Args(values)
{
    ui->setupUi(this);
    ui->laType->setText ("");
    ui->laType->setHidden (true);
    ui->laBus->setText (QString("Addr:%1").arg (data.mBus));
    ui->laService->setText (QString("Service:%1").arg (data.mService));
    ui->laPath->setText (QString("Path:%1").arg (data.mPath));
    ui->laInterface->setText (QString("Interface:%1").arg (data.mInterface));
    ui->laName->setText (QString("method:%1").arg(data.mName));
    ui->leTimeout->setValidator (new QIntValidator(this));
    QString str;
    foreach (auto var, data.argTypes) {
        str.append (var);
    }
    ui->laArgs->setText (QString("args:%1").arg(str));
    m_category = data.type;
    ui->cbToSeq->setEnabled (false);
    ui->cbPropertyGet->setEnabled (false);
    if(data.type == MethodItem ||
            data.type == LocalMethod)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (false);


        m_model = new DBusArgvModel(data.argNames,m_Args,this);

        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);

        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
    }else if(data.type == PropertyItemReadwrite)
    {
        if(values.count ()>0)
        {
            ui->cbPropertyGet->setCheckState (Qt::Unchecked);
        }else
        {
            ui->cbPropertyGet->setCheckState (Qt::Checked);
        }

        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (true);
        ui->btOk->setEnabled (true);
        ui->treeView->setHidden (false);
        if(values.count ()>0)
        {
            ui->gbProperty->setHidden (false);
            m_model = new DBusArgvModel(data.argNames,m_Args,this);
            ui->treeView->setModel (m_model);
            DBusValueDelegate *delegate = new DBusValueDelegate(this);

            ui->treeView->setItemDelegate (delegate);
            ui->treeView->expandAll ();
            connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
            connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
        }else
        {

        }
    }else if(data.type == PropertyItemRead)
    {
        if(values.count ()>0)
        {
            ui->cbPropertyGet->setCheckState (Qt::Unchecked);
        }else
        {
            ui->cbPropertyGet->setCheckState (Qt::Checked);
        }
        ui->treeView->setHidden (false);
        ui->gbProperty->setHidden (false);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (true);
        ui->cbPropertyGet->setEnabled (false);
        ui->cbPropertyGet->setCheckState (Qt::Checked);
        ui->btOk->setEnabled (true);
    }else if(data.type == PropertyItemWrite)
    {
        if(values.count ()>0)
        {
            ui->cbPropertyGet->setCheckState (Qt::Unchecked);
        }else
        {
            ui->cbPropertyGet->setCheckState (Qt::Checked);
        }
        ui->treeView->setHidden (false);
        ui->gbProperty->setHidden (false);
        ui->gbSignal->setHidden (true);
        ui->treeView->setHidden (false);
        ui->laArgs->setText (QString("args:%1").arg(str));

        m_model = new DBusArgvModel(data.argNames,m_Args,this);

        ui->treeView->setModel (m_model);
        DBusValueDelegate *delegate = new DBusValueDelegate(this);

        ui->treeView->setItemDelegate (delegate);
        ui->treeView->expandAll ();
        connect (ui->treeView->selectionModel (),&QItemSelectionModel::selectionChanged,this,&PropertyDlg::InputSelectChange);
        connect (m_model,&DBusArgvModel::commitModelData,this,&PropertyDlg::onInputDataChange);
    }else if(data.type == SignalItem)
    {
        ui->gbProperty->setHidden (true);
        ui->gbSignal->setHidden (false);
        ui->treeView->setHidden (true);
        ui->btOk->setEnabled (true);
        if(values.count ()>0)
        {
            bool ok;
            int timeout = values.first ().m_Values.toInt (&ok);
            if(ok)
            {
                ui->leTimeout->setText (QString::number (timeout));
            }
        }
    }
    adjustSize();
}

PropertyDlg::~PropertyDlg()
{
    delete ui;
}

void PropertyDlg::onInputDataChange(QAbstractItemModel *model, const QModelIndex &index) const
{
    bool ok=false;
    m_model->getArgs (&ok);
    if(ok)
    {
        ui->btOk->setEnabled (true);
    }
}

void PropertyDlg::InputSelectChange(const QItemSelection &selected, const QItemSelection &deselected)
{
    bool ret = true;
    QModelIndexList list = selected.indexes ();
    if(list.count ()>0)
    {
        QModelIndex parentIndex = list.first ().parent ();
        foreach (auto var, list) {
            if(parentIndex != var.parent ())
            {
                ret= false;
                break;
            }
        }
    }
    if(ret)
    {

        QModelIndex index = list.first ();
        DBusArgvItem *item = m_model->getItem (index);
        if(item!=Q_NULLPTR)
        {

            if(item->getParenttype () == DBUS_TYPE_DICT || item->getParenttype () == DBUS_TYPE_ARRAR)
            {
                ui->btAdd->setEnabled (true);
                ui->btDel->setEnabled (true);
                ui->btDown->setEnabled (true);
                ui->btUp->setEnabled (true);
            }else
            {
                ui->btAdd->setEnabled (false);
                ui->btDel->setEnabled (false);
                ui->btDown->setEnabled (false);
                ui->btUp->setEnabled (false);
            }
        }
    }
}

void PropertyDlg::on_btUp_clicked()
{
    QModelIndexList selected = ui->treeView->selectionModel ()->selectedRows ();
    std::sort(selected.begin (),selected.end (),[](QModelIndex a,QModelIndex b){ return a.row ()<b.row ();});
    if (!selected.isEmpty()) {
        int startRow = selected.at(0).row();
        if(startRow == 0)
        {
            return;
        }
        for (const QModelIndex &index : selected) {
            DBusArgvItem *item = m_model->getItem (index);
            if(item->getParenttype () == DBUS_TYPE_ARRAR)
            {
                m_model->moveRow (index.parent(),index.row(), index.parent(),index.row()-1);
            }else if(item->getParenttype () == DBUS_TYPE_DICT)
            {
                int row = index.row();
                if(row%2 ==0 )
                {
                    m_model->moveRow (index.parent(),row, index.parent(),row-2);
                    m_model->moveRow (index.parent(),row+1, index.parent(),row-1);
                }

            }
        }
    }
}

void PropertyDlg::on_btDown_clicked()
{
    QModelIndexList selected = ui->treeView->selectionModel ()->selectedRows ();
    std::sort(selected.begin (),selected.end (),[](QModelIndex a,QModelIndex b){ return a.row ()>b.row ();});
    if (!selected.isEmpty()) {
        int startRow = selected.at(0).row()+1;
        int count = m_model->rowCount (selected.first ().parent ());
        if(startRow>=count)
        {
            return;
        }
        for (const QModelIndex &index : selected) {
            DBusArgvItem *item = m_model->getItem (index);
            if(item->getParenttype () == DBUS_TYPE_ARRAR)
            {
                m_model->moveRow (index.parent(),index.row(), index.parent(),index.row()+1);
            }else if(item->getParenttype () == DBUS_TYPE_DICT)
            {
                int row = index.row();
                if(row%2 ==0 )
                {
                    m_model->moveRow (index.parent(),row+1, index.parent(),row+3);
                    m_model->moveRow (index.parent(),row, index.parent(),row+2);
                }
            }
        }
    }
}

void PropertyDlg::on_btAdd_clicked()
{
    QModelIndex index = ui->treeView->selectionModel ()->currentIndex ();
    DBusArgvItem *item = m_model->getItem (index);
    if(item->getParenttype () == DBUS_TYPE_ARRAR)
    {
        m_model->insertRow(index.row(),index.parent());
    }else if(item->getParenttype () == DBUS_TYPE_DICT)
    {
        if(index.row()%2 ==0)
        {
            m_model->insertRow(index.row(),index.parent());
        }
    }
}

void PropertyDlg::on_btDel_clicked()
{
    QModelIndex index = ui->treeView->selectionModel ()->currentIndex ();
    DBusArgvItem *item = m_model->getItem (index);
    if(item->getParenttype () == DBUS_TYPE_ARRAR)
    {
        m_model->removeRow (index.row (),index.parent ());
    }else if(item->getParenttype () == DBUS_TYPE_DICT)
    {
        if(index.row()%2 ==0)
        {
            m_model->removeRow (index.row (),index.parent ());
        }
    }
}

void PropertyDlg::on_btCancel_clicked()
{
    return this->reject ();
}

void PropertyDlg::on_btOk_clicked()
{
    bool ok = false;
    m_toSeq = false;
    ui->treeView->clearFocus ();

    if(m_category == MethodItem
            || m_category == LocalMethod)
    {
        m_Args = m_model->getArgs (&ok);
        if(ok)
            return this->accept ();
    }
    else if(m_category ==  PropertyItemReadwrite
            || m_category ==  PropertyItemRead
            || m_category ==  PropertyItemWrite )
    {
        if(ui->cbPropertyGet->checkState () == Qt::Checked)
        {
            return this->accept ();
        }else
        {
            m_Args = m_model->getArgs (&ok);
            if(ok)
                return this->accept ();
        }
    }else if(m_category ==  SignalItem)
     {
        DVariant d;
        m_toSeq = ui->cbToSeq->checkState () == Qt::Checked;
        int timeout =ui->leTimeout->text ().toInt (&ok);
        if(ok)
        {
            if(m_Args.count ()>0)
            {
                m_Args.first ().setValue (timeout);
            }else
            {
                d.setValue (timeout);
                m_Args.append (d);
            }
            return this->accept ();
        }

     }

}

QList<DVariant> PropertyDlg::Args() const
{
    return m_Args;
}
void PropertyDlg::on_cbPropertyGet_stateChanged(int arg1)
{
    if(arg1 == Qt::Checked)
    {
        ui->btOk->setEnabled (true);
        ui->treeView->setHidden (true);
    }else
    {
        ui->btOk->setEnabled (false);
        ui->treeView->setHidden (false);
    }
    adjustSize();
}
